import {
  GroupMeta,
  CanvasPlusOptions,
  ShapeOptions,
  RegionOptions
} from './declare/type';
import { isString } from './utils/is';
import ICanvas from './base/canvas';
import Group from './base/group';
import { Arc } from './shape/index';

class CanvasPlus extends ICanvas {
  protected static Group = Group;

  protected group: Group = new CanvasPlus.Group({ label: 'root' });

  protected $container: Element;

  constructor (options: CanvasPlusOptions) {
    super(options.width, options.height);
    super.setCanvasSize();
    this.$container = this.getCanvasContainer(options.container);
    this.$container.appendChild(this.canvas);
  }

  // eslint-disable-next-line class-methods-use-this
  protected getCanvasContainer (container: string | HTMLElement) : Element {
    let $container: Element | null;
    if (isString(container)) {
      $container = document.querySelector(<string>container)
        || document.querySelector('body');
    } else {
      $container = <HTMLElement>container;
    }
    if (!$container) {
      throw new Error('未找到挂载画布容器');
    }
    return $container;
  }

  public getRootGroup () : Group {
    return this.group;
  }

  public addGroup (meta: GroupMeta) : Group {
    const group = new CanvasPlus.Group(meta);
    this.group.addChild(group);
    return group;
  }

  public addShape (type: string, options: ShapeOptions = {}) {
    let shape;
    if (type === 'arc') {
      shape = new Arc(this.createRegionId(), options);
    }
    if (!shape) {
      throw new Error('没有找到该类型的形状');
    }
    return shape;
  }

  public setCanvasSize (width: number, height: number) {
    super.setCanvasSize(width, height);
    // 图形尺寸处理
    this.group.draw(this.ctx2d);
  }

  public draw () {
    this.group.draw(this.ctx2d);
  }

  addEventListener<K extends keyof HTMLElementEventMap>(
    type: K,
    listener: (this: CanvasPlus, ev: HTMLElementEventMap[K] & { region?: RegionOptions }) => any,
    options: boolean | AddEventListenerOptions = false
  ) : (ev: HTMLElementEventMap[K]) => any {
    const eventHandler = (ev: HTMLElementEventMap[K]) => {
      const region = { id: '1' };
      const event = <HTMLElementEventMap[K] & { region?: RegionOptions }>ev;
      event.region = region;
      listener.call(this, event);
    };
    this.canvas.addEventListener(type, eventHandler, options);
    return eventHandler;
  }

  removeEventListener<K extends keyof HTMLElementEventMap> (
    type: K,
    listener: (this: HTMLCanvasElement, ev: HTMLElementEventMap[K]) => any,
    options: boolean | AddEventListenerOptions = false
  ) {
    this.canvas.removeEventListener(type, listener, options);
  }
}

const canvas = new CanvasPlus({
  width: 300,
  height: 300,
  container: 'body'
});
// const group = canvas.addGroup({ label: 'test' });
const group = canvas.getRootGroup();
const arc = canvas.addShape('arc', {});
group.addChild(arc);
canvas.draw();
const listener = canvas.addEventListener('click', (event) => {
  console.log(event);
});
canvas.removeEventListener('click', listener);
